package frame.options.simulation.create.sdn;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.SystemColor;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionListener;

import model.components.networks.sdn.SdnNetwork;

@SuppressWarnings("serial")
public class SdnPanel extends JPanel
{
	public static final String AVAILABLE_LIST = "AvailableList";
	
	public static final String ADD_BUTTON = "Add";
	public static final String ADD_ALL_BUTTON = "AddAll";
	
	public static final String REMOVE_BUTTON = "Remove";
	public static final String REMOVE_ALL_BUTTON = "RemoveAll";
	
	public static final String SELECTED_LIST = "SelectedList";
	
	private JList< SdnNetwork > availableSdnNetworksList;
	public JList< SdnNetwork > getAvailableSdnNetworksList(){ return availableSdnNetworksList; }
	public void setAvailableSdnNetworksList( JList< SdnNetwork > availableSdnNetworksList ){ this.availableSdnNetworksList = availableSdnNetworksList; }
	
	private DefaultListModel< SdnNetwork > availableSdnNetworksListModel;
	public DefaultListModel< SdnNetwork > getAvailableSdnNetworksListModel(){ return this.availableSdnNetworksListModel; }
	public void setAvailableSdnNetworksListModel( DefaultListModel< SdnNetwork > availableSdnNetworksListModel ){ this.availableSdnNetworksListModel = availableSdnNetworksListModel; }
	
    private JButton addButton;
    public JButton getAddButton(){ return this.addButton; }
    public void setAddButton( JButton addButton ){ this.addButton = addButton; }
    
    private JButton addAllButton;
    public JButton getAddAllButton(){ return this.addAllButton; }
    public void setAddAllButton( JButton addAllButton ){ this.addAllButton = addAllButton; }
    
    private JButton removeButton;
    public JButton getRemoveButton(){ return this.removeButton; }
    public void setRemoveButton( JButton removeButton ){ this.removeButton = removeButton; }
    
    private JButton removeAllButton;
    public JButton getRemoveAllButton(){ return this.removeAllButton; }
    public void setRemoveAllButton( JButton removeAllButton ){ this.removeAllButton = removeAllButton; }
    
	private JList< SdnNetwork > selectedSdnNetworksList;
	public JList< SdnNetwork > getSelectedSdnNetworksList(){ return selectedSdnNetworksList; }
	public void setSelectedSdnNetworksList( JList< SdnNetwork > selectedSdnNetworksList ){ this.selectedSdnNetworksList = selectedSdnNetworksList; }
	
	private DefaultListModel< SdnNetwork > selectedSdnNetworksListModel;
	public DefaultListModel< SdnNetwork > getSelectedSdnNetworksListModel(){ return selectedSdnNetworksListModel; }
	public void getSelectedSdnNetworksListModel( DefaultListModel< SdnNetwork > selectedSdnNetworksListModel ){ this.selectedSdnNetworksListModel = selectedSdnNetworksListModel; }
    
    public SdnPanel( List< SdnNetwork > sdnNetworks )
    {
		this.setAvailableSdnNetworksListModel( new DefaultListModel< SdnNetwork >() );
		
		for( SdnNetwork sdnNetwork: sdnNetworks )
			this.getAvailableSdnNetworksListModel().addElement( sdnNetwork );
		
		this.setAvailableSdnNetworksList( new JList< SdnNetwork >( this.getAvailableSdnNetworksListModel() ) );
		this.getAvailableSdnNetworksList().setName( SdnPanel.AVAILABLE_LIST );
		this.getAvailableSdnNetworksList().setCellRenderer( new SdnListCellRenderer() );
		
		this.setAddButton( new JButton( "Add >>" ) );
		this.getAddButton().setName( SdnPanel.ADD_BUTTON );
		this.getAddButton().setEnabled( false );
		
		this.setAddAllButton( new JButton( "Add All >>" ) );
		this.getAddAllButton().setName( SdnPanel.ADD_ALL_BUTTON );
		this.getAddAllButton().setEnabled( true );
		
		this.setRemoveButton( new JButton( "<< Remove" ) );
		this.getRemoveButton().setName( SdnPanel.REMOVE_BUTTON );
		this.getRemoveButton().setEnabled( false );
		
		this.setRemoveAllButton( new JButton( "<< Remove All" ) );
		this.getRemoveAllButton().setName( SdnPanel.REMOVE_ALL_BUTTON );
		this.getRemoveAllButton().setEnabled( false );

        this.getSelectedSdnNetworksListModel( new DefaultListModel< SdnNetwork >() );
        this.setSelectedSdnNetworksList( new JList< SdnNetwork >( this.getSelectedSdnNetworksListModel() ) );
        this.getSelectedSdnNetworksList().setName( SdnPanel.SELECTED_LIST );
        this.getSelectedSdnNetworksList().setCellRenderer( new SdnListCellRenderer() );
		
		this.setLayout( new java.awt.BorderLayout() );
        this.add( this.titlePanel(), BorderLayout.NORTH );
        this.add( this.contentPanel(), BorderLayout.CENTER );
    }
    
	private JPanel titlePanel()
	{
        JLabel titleLabel = new JLabel( "SDN networks" );
        titleLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 14 ) );
        titleLabel.setBorder( new EmptyBorder( new Insets( 10, 10, 10, 10 ) ) );
        titleLabel.setOpaque( true );
        
        JSeparator separator = new JSeparator();
        
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout( new java.awt.BorderLayout() );
        titlePanel.setBackground( Color.gray );
        titlePanel.add( titleLabel, BorderLayout.CENTER );
        titlePanel.add( separator, BorderLayout.SOUTH );
        
        return titlePanel;
	}
	
	private JPanel contentPanel()
	{
    	JPanel contentPanel = new JPanel();
    	contentPanel.setBorder( new EmptyBorder( new Insets( 50, 50, 50, 50 ) ) );
        contentPanel.add( this.availablePanel() );
        contentPanel.add( this.buttonsPanel() );
        contentPanel.add( this.selectedPanel() );
        
        return contentPanel;
	}
	
	private JPanel availablePanel()
	{
    	JLabel availableLabel = new JLabel( "Available" );
        availableLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 12 ) );
        availableLabel.setAlignmentX( JPanel.CENTER_ALIGNMENT );
        
		JScrollPane availableScrollPane = new JScrollPane( this.getAvailableSdnNetworksList() );
		availableScrollPane.setPreferredSize( new Dimension( 200, 250 ) );
		availableScrollPane.setBorder( BorderFactory.createLineBorder( SystemColor.activeCaption, 2 ) );
				
		JPanel availablePanel = new JPanel();
        availablePanel.setLayout( new BoxLayout( availablePanel, BoxLayout.PAGE_AXIS ) );
        availablePanel.add( availableLabel );
        availablePanel.add( Box.createRigidArea( new Dimension( 0, 5 ) ) );
		availablePanel.add( availableScrollPane );
		
		return availablePanel;
	}
	
	private JPanel buttonsPanel()
	{
		JPanel buttonsPanel = new JPanel();
		buttonsPanel.setLayout( new GridLayout( 0, 1 ) );
		buttonsPanel.add( this.getAddButton() );
		buttonsPanel.add( this.getAddAllButton() );		
		buttonsPanel.add( new JLabel() );
		buttonsPanel.add( this.getRemoveButton() );
		buttonsPanel.add( this.getRemoveAllButton() );
		
		return buttonsPanel;
	}
	
	private JPanel selectedPanel()
	{
		JLabel selectedLabel = new JLabel( "Selected" );
		selectedLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 12 ) );
		selectedLabel.setAlignmentX( JPanel.CENTER_ALIGNMENT );
		
        JScrollPane selectedScrollPanel = new JScrollPane( this.getSelectedSdnNetworksList() );
		selectedScrollPanel.setPreferredSize( new Dimension( 200, 250 ) );
		selectedScrollPanel.setBorder( BorderFactory.createLineBorder( SystemColor.activeCaption, 2 ) );
		
		JPanel selectedPanel = new JPanel();
		selectedPanel.setLayout( new BoxLayout( selectedPanel, BoxLayout.Y_AXIS ) );
		selectedPanel.add( selectedLabel );
        selectedPanel.add( Box.createRigidArea( new Dimension( 0, 5 ) ) );
		selectedPanel.add( selectedScrollPanel );
		
		return selectedPanel;
	}
	
	public void addListeners( ActionListener actionListener, MouseListener mouseListener, ListSelectionListener listSelectionListener )
	{
		this.getAvailableSdnNetworksList().addMouseListener( mouseListener );
		this.getAvailableSdnNetworksList().addListSelectionListener( listSelectionListener );
		
		this.getAddButton().addActionListener( actionListener );
		this.getAddAllButton().addActionListener( actionListener );
		
		this.getRemoveButton().addActionListener( actionListener );
		this.getRemoveAllButton().addActionListener( actionListener );
		
		this.getSelectedSdnNetworksList().addMouseListener( mouseListener );
		this.getSelectedSdnNetworksList().addListSelectionListener( listSelectionListener );
    }
	
	public List< SdnNetwork > getSelectedSdnNetworks()
	{
		List< SdnNetwork > selectedSdnNetworks = new ArrayList< SdnNetwork >();
		
		for( int i = 0; i < this.getSelectedSdnNetworksListModel().size(); i++ )
		{
			SdnNetwork sdnNetwork = this.getSelectedSdnNetworksListModel().get( i );
			sdnNetwork.setSelected( true );
			
			selectedSdnNetworks.add( sdnNetwork );
		}
		
		return selectedSdnNetworks;
	}
	
	public void mouseDoubleClicked( JList< SdnNetwork > sdnNetworksList, int sdnNetworksListIndex )
	{
		SdnNetwork sdnNetwork = sdnNetworksList.getModel().getElementAt( sdnNetworksListIndex );
		
		if( sdnNetworksList.getName().equals( SdnPanel.AVAILABLE_LIST ) )
		{
			this.getSelectedSdnNetworksListModel().addElement( sdnNetwork );
			this.getAvailableSdnNetworksListModel().removeElementAt( sdnNetworksListIndex );
		}
		else
		{
			this.getAvailableSdnNetworksListModel().addElement( sdnNetwork );
			this.getSelectedSdnNetworksListModel().removeElementAt( sdnNetworksListIndex );
		}
	}
	
	public void buttonClicked( JButton button )
	{
		if( button.getName().equals( SdnPanel.ADD_BUTTON ) )
		{
			for( SdnNetwork sdnNetwork: this.getAvailableSdnNetworksList().getSelectedValuesList() )
			{
				this.getSelectedSdnNetworksListModel().addElement( sdnNetwork );
				this.getAvailableSdnNetworksListModel().removeElement( sdnNetwork );
			}
		}
		else if( button.getName().equals( SdnPanel.ADD_ALL_BUTTON ) )
		{
			for( int i = 0; i < this.getAvailableSdnNetworksListModel().getSize(); i++ )
				this.getSelectedSdnNetworksListModel().addElement( this.getAvailableSdnNetworksListModel().getElementAt( i ) );
			
			this.getAvailableSdnNetworksListModel().removeAllElements();
		}
		else if( button.getName().equals( SdnPanel.REMOVE_BUTTON ) )
		{
			for( SdnNetwork sdnNetwork: this.getSelectedSdnNetworksList().getSelectedValuesList() )
			{
				this.getAvailableSdnNetworksListModel().addElement( sdnNetwork );
				this.getSelectedSdnNetworksListModel().removeElement( sdnNetwork );
			}
		}
		else if( button.getName().equals( SdnPanel.REMOVE_ALL_BUTTON ) )
		{
			for( int i = 0; i < this.getSelectedSdnNetworksListModel().getSize(); i++ )
				this.getAvailableSdnNetworksListModel().addElement( this.getSelectedSdnNetworksListModel().getElementAt( i ) );
			
			this.getSelectedSdnNetworksListModel().removeAllElements();
		}
	}
	
	public void updateButtons()
	{
		if( !this.getAvailableSdnNetworksList().isSelectionEmpty() )
			this.getAddButton().setEnabled( true );
		else
			this.getAddButton().setEnabled( false );
		
		if( this.getAvailableSdnNetworksListModel().getSize() > 0 )
			this.getAddAllButton().setEnabled( true );
		else
			this.getAddAllButton().setEnabled( false );
		
		if( !this.getSelectedSdnNetworksList().isSelectionEmpty() )
			this.getRemoveButton().setEnabled( true );
		else
			this.getRemoveButton().setEnabled( false );
		
		if( this.getSelectedSdnNetworksListModel().getSize() > 0 )
			this.getRemoveAllButton().setEnabled( true );
		else
			this.getRemoveAllButton().setEnabled( false );
	}
	
}
